﻿using System;

namespace Nextensions.Basic
{
    public abstract class StatusUpdateWorker: IStatusUpdateWorker
    {
        public delegate void StatusUpdateHandler(string message, int percentDone, int stepIndex, int stepCount);
        public delegate void StatusUpdateHandler2(InfoLevel level, string message, int percentDone, int stepIndex, int stepCount);
        public event StatusUpdateHandler StatusUpdate;
        public event StatusUpdateHandler2 StatusUpdate2;

        protected int _currentStep = 0;

        public StatusUpdateWorker()
        {
            AutoIncrementStepOnUpdate = true;
        }

        private int CalculateDoneness()
        {
            if (TotalSteps == 0 || _currentStep == 0)
                return 0;
            else
                return (int)((float)_currentStep / (float)TotalSteps * 100);
        }

        protected void UpdateF(string format, params object[] args)
        {
            Update(String.Format(format, args));
        }

        protected void Update(string message)
        {
            Update(InfoLevel.Info, message);
        }

        protected void Update(InfoLevel level, string message)
        {
            if (AutoIncrementStepOnUpdate)
                _currentStep++;

            if (StatusUpdate != null)
                StatusUpdate(message, CalculateDoneness(), _currentStep, TotalSteps);

            if (StatusUpdate2 != null)
                StatusUpdate2(level, message, CalculateDoneness(), _currentStep, TotalSteps);
        }

        protected abstract int TotalSteps
        {
            get;
        }

        protected void IncrementStep()
        {
            _currentStep++;
        }

        protected bool AutoIncrementStepOnUpdate
        {
            get;
            set;
        }

        protected void Log(InfoLevel level, string format, params object[] args)
        {
            Log(level, String.Format(format, args));
        }

        protected void Log(InfoLevel level, string message)
        {
            Update(level, message);
        }
    }
}
